Previous Page TOC Next Page


2 — Exploiting the Features of Visual Basic 4.0

by Conrad Scott

Visual Basic 4.0 is an exciting new version of Visual Basic that adds many new features and enhancements to move Visual Basic to a new level in software design and development. This new version of Visual Basic uses Visual Basic for Applications (VBA) as its language engine. Several new keywords are added to the language to support the development of applications using OLE Automation. The VBX is replaced with the new generation of custom controls: the OCX. The Visual Basic interactive development environment (IDE) is significantly enhanced (see Figure 2.1); tasks such as adding a custom control to a project or viewing objects available within a project are simplified. This chapter outlines the new features of Visual Basic 4.0. Each new feature is fully explained and examples are provided where appropriate. A sample application is developed using OLE Automation and the Visual Basic 4.0 class module.


Figure 2.1. The Visual Basic 4.0 interactive development environment (IDE).

Visual Basic 4.0 also has many new features you can incorporate into existing projects. This chapter outlines the steps necessary to upgrade a project to Visual Basic 4.0 and explains some of the pitfalls you may encounter along the way. A step-by-step procedure is provided for converting a project from earlier versions of Visual Basic to VB4. Methods are covered for incorporating many new features of Visual Basic 4.0 into existing projects. Several sample programs are also provided.

Visual Basic for Applications (VBA)

Visual Basic 4.0 includes the Visual Basic for Applications (VBA) language. VBA is the language currently used in applications such as Microsoft Word and Excel. The inclusion of the language provides a new level of interaction between Visual Basic and Microsoft applications. For example, using VBA, a Visual Basic 4.0 application can create an instance of Microsoft Excel, add a workbook, and imbed a chart in the workbook. All this can be done directly from Visual Basic in code. The instance of Excel and its components are created using OLE Automation. The inclusion of the VBA language allows Visual Basic to interact with other Microsoft applications without translating the language elements to something Visual Basic can understand. For example, you can use Microsoft Word to create a macro you can then copy directly to Visual Basic for inclusion in a procedure. Little or no translation is necessary to use the macro's code with Visual Basic. See Chapter 24 for more information about using Word macros in Visual Basic 4.0.

The Visual Basic Interactive Development Environment (IDE)

Many changes have been made to Visual Basic for version 4.0. The following sections cover the enhancements and changes to the Visual Basic IDE. Items that remain the same from version 3 to version 4.0 are not discussed.

The File | Make OLE DLL File Option


NOTE

The Make OLE DLL File option is available in 32-bit Visual Basic only.

The first addition to the Visual Basic IDE menu is the File | Make OLE DLL File option. This option is used to create OLE Automation objects you can expose to other applications and development environments. Once the OLE object is developed using the Visual Basic class module, the Make OLE DLL File option is used to compile the object into a DLL. The object is then added to other projects using the References dialog box (accessed by selecting Tools | References). Creating OLE automation objects using the class module is covered later in this chapter.

The Options button on the Make OLE DLL File dialog box leads to another dialog box from which you can specify a number of options such as version number, a title for the object, and the icon (if the object is visible). The OLE DLL Options dialog box is shown in Figure 2.2. The bottom section of this dialog box presents a number of different items whose information can be included in the OLE DLL. These items include Comments, Company Name, Legal Trademarks, and so on.


Figure 2.2. The OLE DLL Options dialog box.

The OLE DLL Options dialog box allows you to place several pieces of information directly into your OLE DLL. Access the dialog box by selecting File | Make OLE DLL File from the main menu and clicking the Options button in the Make OLE DLL File dialog box.

The Edit | Lock Controls Option

Another addition to the IDE is the Lock Controls feature. This option is accessed by selecting Edit | Lock Controls from the main menu. This option locks all the controls on the currently selected form. All the controls on the form are locked; you cannot select individual controls for locking.

There are a couple of advantages to this option. Once the design of a form is complete, you can lock the controls in place. Locking the controls marks the form as being graphically complete. You can still double-click any of the controls on the form to bring up the code window. Modifications to the code can be made without danger of changing the position of a control on a form. If you are creating a 32-bit version of an existing application (that is, you are porting an existing application from version 3 to 4), you can lock the controls to be sure that both versions of the application maintain the same graphical look.

The View | Procedure Definition Option

The View Procedure Definition feature allows you to locate the origin of a procedure. If you have used Visual C++, this feature should be familiar to you. If you call a procedure and cannot remember where the procedure definition is, this option is of great use. Imagine that you create the following function in Module1:

Function Hello()

    MsgBox "Have a nice day"

    Hello = 0

End Function

Next, you call this function from Form1's command button:

Private Sub Command1_Click()

    x = Hello

End Sub

Now suppose that your project has grown significantly (say, to 25 modules) and you can no longer remember in which module the Hello function resides. To solve this, do the following:

  1. Open the Private Sub Command1_Click() procedure from Form1.

  2. Click the function name (in this case, Hello).

  3. Choose View | Procedure Definition from the main menu.

Module1 opens to display the Hello function. The Procedure Definition is a handy tool for large projects. Another place in which this feature has great benefit is in the modification of existing code. This feature precludes much of the searching that traditionally goes on when a programmer inherits source code written by others.

The View | Last Position Option

A helpful new feature of Visual Basic 4.0 is available by choosing View | Last Position. This action places the cursor in its previous position. This can be very helpful if you are browsing through a number of modules and want to go back to where you just were. The Last Position feature "thinks" like an undo feature but does not undo anything; instead, it merely moves the cursor back one action. Imagine that you have three modules: Module1, Module2, and Module3. You look at a procedure in each of the modules (1, 2, and then 3). Select View | Last Position; the cursor moves from the procedure being viewed in Module3 to the Module2 procedure (the one viewed just before the one you are currently viewing). Select View | Last Position again to bring up Module1's procedure. If the module is closed, Visual Basic opens it. The Last Position feature works wonders when you are stepping through large projects.

The Object Browser

Yet another addition to the Visual Basic IDE is the Object Browser. Access the Object Browser by choosing View | Object Browser (see Figure 2.3). The Object Browser presents a list of the different objects available to your application. Each of the objects lists the properties and methods it exposes.


Figure 2.3. The Visual Basic Object Browser dialog box displays the Visual Basic for Applications (VBA) objects.

Two types of objects are available to an application: those within Visual Basic and those provided by other applications. The objects provided by other applications are accessed through OLE Automation. To select the object you want to view, choose an object from the available items in the Libraries/Projects combo box. The Classes/Modules list box lists the items exposed by the selected object; the Methods/Properties list box displays the properties and methods exposed by the object.

Imagine that you create a project (Project1) with one form (Form1). On the form, you place a text box. Now open the Object Browser and select Project1 from the Libraries/Projects combo box. The Classes/Modules section contains one item: Form1. The Methods/Properties section contains all the properties and methods for Form1. These are the normal properties and methods the form already includes. Scroll through the list in the Methods/Properties list box. Notice the Text1 and Text1_Change [Sub] items. Because the text box is now a part of Form1, it and the properties and methods it exposes are displayed in this list as well.

Another use for the Object Browser is during the creation of a procedure using a method an object in the list exposes. Imagine that you want to create a new procedure using one of the objects VBA exposes. Using the Object Browser, you can automatically paste a Visual Basic template for the selected method or property. The following steps accomplish this:

  1. Create a new project and double-click Form1 to display the code window.

  2. Place the cursor in the Form_Load procedure (click above the End Sub statement).

  3. Open the Object Browser and select VBA—Visual Basic for Applications from the Libraries/Projects combo box. Notice that the Collection object is highlighted in the Classes/Modules section and that the Add item is highlighted in the Methods/Properties list box. Click the Paste button.

The statement pasted into the Form_Load procedure contains the Visual Basic syntax necessary to use the Add method of the Collections object within VBA.

Another feature of the Object Browser is its ability to quickly locate procedures and functions within a project. Select the desired procedure or function from the browser and click the Show button; Visual Basic displays the code for that item. To use the Show feature, follow these steps:

  1. Create a new project (or use the current one if you followed the steps for the last example).

  2. Place a text box on the form.

  3. Start the Object Browser and select Project1 from the Libraries/Projects combo box.

  4. Click Form1 in the Classes/Modules list box.

  5. Choose Text1_Change [Sub] from the Methods/Properties list box.

  6. Click the Show button.

The code window for Form1 opens, displaying the Private Sub Text1_Change() procedure.

The Debug Window

The Visual Basic Debug Window is used to view or change the value of statements or variables at design time. The window becomes active when the interactive development environment (IDE) is in break mode (see Figure 2.4).


Figure 2.4. The Visual Basic Debug Window.

The three sections of the window are the Procedure box, the Watch pane, and the Immediate pane.

There are three major sections to the Break window. Each of these sections of the Debug Window is described in the following sections.

The Procedure Box

The Procedure box displays the Project, Module, and Procedure name that was active when the application was placed into break mode. To the right of this section is a command button with three dots; click this button to display the Calls window. The Calls window shows a list of all the procedures that were called but that have not yet completed. Using the example from the preceding section, Form1's Private Sub Command1_Click() procedure calls the Hello function in Module1. Set a break point in the middle of the Hello function. Once the break point is hit, the application goes into break mode and the Debug Window appears. Click the Calls button; the Private Sub Command1_Click() procedure appears in the Calls window because it has not yet completed. Click the Show button in the Calls window to display the code window for the selected procedure. The Calls window is especially effective when using recursive functions.

The Watch Pane

The Watch pane of the Debug window displays information about variables you have placed a watch on. To add a watch to a variable, use the mouse to select a variable in a code window (procedure, function, and so on) and choose Tools | Add Watch. The Add Watch window is displayed. The expression you want to place a watch on appears in the Expression section of this window. The center section lists the procedure, module, and project associated with the variable. The bottom section of the Add Watch window provides a choice of three types of watches. The Watch Expression displays the value of the expression in the ???Watch??? window. The Break When Value Is True option and Break When Value Changes option cause Visual Basic to go into break mode if one of those conditions occurs. Click OK to add the watch. If the application is not yet running, the Out of Context message is displayed, indicating that the variable cannot be tracked at this time. When the application is placed in break mode, the value for the selected variable is displayed.

The Immediate Pane

The immediate pane allows the getting and setting of values within the application. For example, if you did not add a variable to the watch window, you can view the value of the variable by printing it to the Debug Window's Immediate pane. To do this, type a question mark followed by the variable name. For example, to get the value of variable X, type the following in the Immediate Pane and press Enter:

?X

The value of X is displayed on the next line of the Immediate pane. You can also set a value for X using an assignment statement like the following:

X = 50

This statement sets the value of X within the program to 50. This capability is advantageous if you want to reset a loop variable to 0 during debugging.


NOTE

The immediate pane can be used only in Break mode.

View Color Palette

The color palette is used to set the colors for forms and controls. The palette is accessed by choosing View | Color Palette from the main menu. Foreground and background colors can be set using the palette. Follow these steps to use the color palette:

  1. Open a form.

  2. Open the palette by choosing View | Color Palette.

  3. Use the mouse to select the form or a control on the form.

  4. Click the palette's title bar to give it the focus. Notice that the palette contains a square with an inner and outer section.

  5. Click the inner section of the palette's square to change the foreground color of the selected form or control. Click the outer section to set the background color.

Using the color palette is the equivalent of using the Properties dialog box to set the value for the object. However, the palette approach is quicker and more convenient. You can define custom colors by following these steps:

  1. Click the Custom Colors button on the color palette.

  2. Click the first color block in the section (initially, each block in the row is white).

  3. Click the Define Colors button.

  4. Manipulate the color using the six available categories.

  5. Click Add Color to create the custom color; click Close to quit.

Start with Full Compile Command

The Run | Start with Full Compile menu option starts the Visual Basic application much like the Run menu item in Visual Basic 3.0 does. This command is used primarily when your application is acting as an OLE server. With this option, the application is fully compiled and then run. If you use only the Start command and your application has errors that show up when the application is compiled, the client applications may be left with invalid object references.

The Step to Cursor Option

The Step to Cursor option is a new element added to the Run menu. This option is used only in break mode. To use Step to Cursor, follow these steps:

  1. Run your project and go into break mode.

  2. Click the line you want to step to and choose Run | Step to Cursor.

The line you select must be after the current line. An example of Step to Cursor follows. Imagine that you have the following procedure:

Private Sub Command1_Click()

    Dim x As Integer

    Dim y As Integer

    Dim z As Integer

    x = 7

    For x = 1 To 100

        DoEvents

    Next x

    y = 4

    z = x + y

    y = z - x

    x = z - y

    x = x + 1

End Sub

There is a breakpoint set on the line x = 7. Once you are inside the procedure (execution has stopped at the break point), you decide you want to step to the line y = z - x. To avoid stepping through the very productive DoEvents loop, click the line y = z - x and choose Run | Step to Cursor. The program executes until it reaches that line and then stops.

Addition of Custom Controls

Visual Basic 4.0 has added a much needed option to its package of new features: You can now add custom controls to a project without the previous difficulty of searching the system for them. Choose Tools | Custom Controls from the main menu; the Custom Controls dialog box displays. Visual Basic automatically searches your system for a list of the available custom controls. Remember that these controls must be OCXes (VBXes are not supported under Visual Basic 4.0). To select a control to add to your project, browse the list box of available controls and click the checkbox for each control you want to add. The section at the bottom right of the dialog box allows you to choose the types of objects displayed in the dialog box. There are three categories:

The section along the bottom of the dialog box displays the name of the current item as well as the fully qualified path to its location.

If you want to add an item to your project but that item is not displayed in the list, click the Browse button. A common dialog box is displayed, allowing you to select a specific file to add to the project.

Click OK when you have selected the items you want to add to your project. The dialog box closes and the custom controls and insertable objects are added to the toolbar. This is a much simpler method than the File | Add File method of Visual Basic 3.0.

When you open a project created in an earlier version of Visual Basic, you are asked whether the custom controls should be updated. Visual Basic 4.0 updates your project to include the OCX version of any control contained in your project. This applies to standard controls only. For third-party controls, you must either upgrade the VBX to an OCX or eliminate the control from the application. Most third-party tools vendors, such as MicroHelp, Inc., provide a complete set of OCX controls for use with Visual Basic 4.0. These controls are provided in both 16-bit and 32-bit versions.


NOTE

MicroHelp is the largest maker of third-party add-on tools for Visual Basic. MicroHelp, Inc. offers a Communications Library that is considerably faster than the 19,200 baud controls supplied with Visual Basic 4.0. The control supports numerous additional protocols and emulations and can be substituted for the Visual Basic communications control without modifying existing code. MicroHelp, Inc. also offers OLETools, a product containing more than 50 16-bit and 32-bit custom OCXes for development with Visual Basic 4.0.

You can reach MicroHelp at 1-800-922-3383 or (770) 516-0898.

The References Dialog Box

The References dialog box lets you select from a list of OLE objects to add to your project. Items in the list are OLE objects exposed for use by other applications. To select an object, check its checkbox. Remove the check to deselect that object. These objects are not actually added to your project; instead, a reference is set to the object's object library. (An object library contains the properties and methods an object exposes.) To view the properties and methods of an OLE object, use the Object Browser.

OLE Automation

You encounter two types of objects when creating applications for Visual Basic: objects that Visual Basic provides and objects provided by other applications. The objects Visual Basic provides are familiar to you: forms, controls, and so on. (You can also create your own objects from within Visual Basic.) The objects provided by other applications are accessed with OLE Automation. Applications create objects they expose to other applications. The term expose simply means to make an object or its properties and methods available for use by other applications or development environments.

An example of an application that exposes objects is Microsoft Excel. Excel exposes many different objects to applications. One of these objects is a spreadsheet. A Visual Basic application can create an instance of the spreadsheet object and manipulate it using the properties and methods the object exposes. For more information on OLE Automation with Microsoft Excel and Word, see Chapter 24, "Microsoft Office."

All the objects contained within Visual Basic are based on a hierarchy. Imagine that you are accessing objects on a form. The code you use to access the objects is in a module. To access a text box on a form, the Form object is called and then the text box is called.

Form1.Text1.Text = "This is an object hierarchy"

This line of code accesses the text box object that belongs to Form1. Another type of object in Visual Basic is one you create at runtime. For example, you can create an instance of Form1 by doing the following:

Sub CreateForm()

    Dim frmNew As New Form1

    Static iTop as Integer

    frmNew.Show

    iTop = iTop + 50

End Sub

This procedure creates a new instance of Form1 and then shows it. If this procedure is attached to a command button and you click the command button five times, five new instances of Form1 are created and then shown. The iTop = iTop + 50 statement is used for demonstration purposes so that the forms are not stacked directly on top of each other (this may give the impression that there is only one form and the others are not being created).

This type of interaction also applies when dealing with objects another application exposes. To create and access a spreadsheet object, the hierarchy of the application.workbook.spreadsheet must be followed. Each application that exposes objects provides a hierarchy list of objects.

To view the list of objects for Microsoft Excel, do the following:

  1. From the main Excel menu, choose Help | Contents.

  2. Choose Programming with Visual Basic to jump to a screen entitled Visual Basic Reference.

  3. Choose Microsoft Excel Object Model to jump to the listing of objects Excel exposes to other applications. You can expand an item that contains a red arrow to reveal additional objects that the item contains.

If you are planning to use an object frequently, you can add it to your project using the Custom Controls dialog box described in "Addition of Custom Controls," earlier in this chapter.

More about OLE Automation

OLE Automation allows applications to expose objects to other applications that support (or develop) OLE. Think of this functionality as an extension of Visual Basic. VB has objects (command buttons, text boxes, forms, and so on). These objects have properties and methods; for example, the text box has a text property (Text1.Text = "Hello") and a Change method (Text1_Change). OLE Automation takes this a step—or more precisely, several steps—further by allowing different applications to "expose" objects to other applications. Exposing an object allows another application to see and manipulate the object. For example, the following line of Visual Basic code creates a new instance of Microsoft Excel:

Set objApp = CreateObject("Excel.Application")

The new instance of the application is stored in the variable objApp. The same functionality is applied to the objects Excel exposes.

The object model referred to in step 3 in the preceding section is a list of all the objects Microsoft Excel exposes to other applications. These objects are accessed with Visual Basic much like properties and methods for controls (Text1.Text, Command1_Click, and so on). To use an object, you must first create it with the CreateObject function. If the object already exists (as a saved spreadsheet, for example), you can use the GetObject function. Each object must be assigned to a variable; that variable is what is used in the hierarchical manipulation of the object.

Set objApp = CreateObject("Excel.Application")

Set objWorkBook = objApp.WorkBooks.Add

Set objSpreadSheet1 = objApp.ActiveWorkbook.ActiveSheet

These three lines of code create an object instance of Microsoft Excel and store it in the variable objApp. A new workbook is then created by using the objApp variable (the instance of Excel). Finally, the active spreadsheet within the workbook is assigned the variable objSpreadSheet1. You then access the spreadsheet by using objApp.objWorkBook.objSpreadSheet1.


TIP

To avoid bulky code, assign an object at the bottom of a hierarchical list its own variable name with a statement like this one:

Set objASheet = objApp.ActiveWorkbook.ActiveSheet

Now each time you use the spreadsheet, you can call it with objASheet instead of objApp.ActiveWorkBook.ActiveSheet. This saves typing time and makes the source code more readable.

Be careful that you use the proper hierarchy and that every one of the objects is a member of its parent object. Because this is not always apparent, diligence is in order. For example, to set the caption in a spreadsheet cell (or range of cells), it would seem logical to use objSpreadSheet1Range.Caption. However, this statement does not work because the proper structure requires the use of the Characters object. The spreadsheet contains the Characters object and the Characters object contains the caption property. Therefore, the proper statement is as follows:

objSpreadSheet1Range.Characters.Caption = sValue

In this case, objSpreadSheet1Range is a range of cells within the worksheet (this range can be one cell).

To find the properties and methods exposed by an object, click the object in the object model. This brings up a help sheet with two jumps: properties and methods. Using this approach, you can establish the downward order of objects within Excel. Each application should have a list that roughly follows this format. Unfortunately (at least with the object model in Excel), it is not easy to go in reverse. For example, if you know that you want to set the caption of the spreadsheet cell, it can be difficult to determine that you have to go through the Characters object.

All the items listed in the preceding code fragments are OLE objects exposed by Excel for use in other applications.

OLE Automation has been significantly enhanced in Visual Basic 4.0. Visual Basic for Applications (VBA) version 2.0 is included as part of Visual Basic 4.0 (it is also the language used in Microsoft Excel and Project). The inclusion of VBA provides greater control over OLE automation directly from Visual Basic.

Chapter 24 details the creation of an Excel application. In that chapter, you create an Excel workbook and set up the background color, fonts, and so on. Next, you add several command buttons to the first spreadsheet in the workbook. These command buttons are connected to a module containing functions that populate data, format cells, select cells, and so on. This module is added to the Visual Basic code. The next step adds a chart to the spreadsheet; the chart uses existing spreadsheet data for its values. A Microsoft Word document is then embedded into the spreadsheet; the document is connected to an existing Word DOC file. Finally, a title is added to the spreadsheet.

There are several interesting things to note here. Before creating the application, nothing existed in Excel. The entire application is created with code directly from Visual Basic. This is possible because of the inclusion of VBA into the language. The code includes the "wiring" of the command buttons to the functions in the module. Also, all objects (spreadsheets, charts, modules, and so on) are OLE objects created using OLE Automation.

The properties and methods of an OLE object allow one application to use functionality that resides within another application without recreating the code that does so. In Visual Basic, the class module is the mechanism used to create such objects.

Class Modules

A new feature of Visual Basic 4.0 is the class module. Before discussing class modules, a definition of the term class is in order. A class is a collection of related data objects and the functions used to manipulate them. In Visual Basic 4.0, these items are all stored in a module called a class module. If you are not a C++ programmer, this concept may seem a bit foreign; this section delves into this topic further.

Imagine that you are writing an application that reads data from a file, does mathematical calculations on the data, and then returns it to the file. Different calculations are performed depending on the data retrieved. To organize your application, you create two modules: FILEIO.BAS and MATH.BAS. In each of these modules, you create the necessary functions to perform the task. Each of these modules falls into a class (File I/O and Mathematics). Although you have not created classes, this analogy should help to explain the principle of classes.

Class modules somewhat resemble Visual Basic modules in that they can contain function declarations, functions, and procedures. However, class modules also allow the inclusion of property procedures and can be accessed by other applications through OLE Automation. Property procedures are structured like functions and are used to get and set the properties of objects within the class. Property procedures are primarily used in OLE Automation. In OLE Automation, other applications can manipulate objects your application exposes. If you have a class module with public functions, other applications can call these functions to manipulate their objects. Remember: In the class structure, there are objects and these objects are manipulated by their functions.

Visual Basic 4.0 provides a good example of classes in the sample application SOCCER. This application is located in the directory C:\VB4\SAMPLES\OLESERV (VB4 being the location of Visual Basic 4.0). You must have installed the samples for this directory to be present. This directory contains two projects: CLIENT.VBP and SOCCER.VBP. SOCCER.VBP is the OLE server that responds to requests from the interface CLIENT.VBP. This application is structured after a soccer league. There is one class module for each of the objects:

Class Module


Contents


LEAGUE

Data about the league

PLAYER

Data about a specific player

PLAYERS

Data about players on a team

TEAM

Data about a team

TEAMS

Data about a collection of teams

Items can be added to each of the class modules (a member can be added to a team, a team added to a league, and so on) and items can be removed. The class can be queried for information. All interaction with the SOCCER.VBP application is done using OLE Automation through CLIENT.VBP.

Several elements are involved in the creation of an OLE object using the Visual Basic 4.0 class module. Each of these elements is discussed in the following sections:

Properties

To create the properties an object exposes, the property itself must be defined. Any property to be used by another application must be declared as public. Visual Basic uses the Public keyword to indicate that a property can be accessed by other applications performing OLE Automation. The declaration of a property is as follows:

Public PropertyName as Integer

Any data type can be used in place of integer. This statement defines the property name other applications must use to interact with your OLE object. This name should be user friendly so that your library of properties and methods is easy to understand and use. The following example created a property that is difficult to read:

Public pLstPd as Integer

Remember that you are declaring the name that others have to use; the following example is easier to understand:

Public LastPay as Integer

Once the property is defined, you must then create property procedures.

Property Procedures

Property procedures are used to set and get the properties of the class module (OLE object). A property procedure is a function or procedure inside the class module that is called when the user gets or sets a property within the module. Imagine that you have a class module object named Draw. The Draw object has a property called DrawItem. To get or set the DrawItem property, you must first create an instance of the Draw object:

Dim objDraw as Draw

Then you set the object's DrawItem property using the standard property-setting statement:

objDraw.DrawItem = "Pen"

At this point, your class module invokes the Property Let method for the object and attempts to set the DrawItem property to "Pen". The Property Let method validates that this is a legal setting and notifies the user appropriately.

Next, you query the objDraw object's DrawItem property for its value:

'Variable where we store the DrawItem property value.

Dim sWhat as String

sWhat = objDraw.DrawItem
Methods

Imagine that there are five objects available for drawing and that each time the objDraw.DrawItem property is set, one of these objects is allocated for use (also imagine that there is a objDraw.KillItem property that deallocates an object). You need a method that calculates how many DrawItem objects remain for use. If five items have been allocated and the user tries to allocate an additional item, this method should notify the user that this is not allowed. The method should be executed before the Property Let procedure that allocates a new drawing item. If the maximum number of drawing objects has not yet been allocated, the Property Let statement is executed. In this example, the Property Let procedure probably does something like GetStockObject() to create a new drawing object. When the KillItem property is set (for example, ObjDraw.KillItem = "Pen") DestroyObject() is called inside the property procedure to delete the pen.

This is a very effective way to handle difficult operations in Visual Basic. The user can access your drawing object's methods and properties with simple statements such as objDraw.DrawItem = "Pen". Behind the scenes, your code may be performing complex operations transparent to the user. Your OLE Automation object is therefore very effective and easy to use. Other properties may include the type of object to draw and where to draw it.

The Customer Account Example

This section creates an OLE Automation object using a class module. This module sets up and maintains an account at a local shop. The class object name is Account.

The properties and methods of this object allow you to set up new customers, make purchases, and query the account for information. When you process a transaction against the account, you verify that the customer is not over his or her limit.

First, create a new class module: Select Insert | Class Module from the main menu. Double-click the class module to open its code window. Press F4 to display the property window for the class module.


NOTE

The class module code window must be open to display its property sheet.

Change the Name property to Account. When a new instance of this object is created, it references the Name property (you create an instance of this object in the form procedure later).

In the general declarations section of the class module, place the following declarations:

Private c_CustName As String

Private c_CurrentBalance As Double

Private c_NewPurchaseAmount As Double

These are private variables used by the Account class to store data. These variables are called member variables (this term comes from the C++ language). Because they are declared as Private, they are not visible outside the class module (by other applications or even by the current VB application).

The Account class has three properties. These properties correspond to the member variables:

Property


Member Variable


CustomerName

c_CustName

CurrentBalance

c_CurrentBalance

NewPurchaseAmount

c_NewPurchaseAmount


NOTE

The c_ indicates that this is a private class variable not visible outside the Account object. This notation is of my choosing, but in a moment, you will see that it clarifies things significantly.

The next step is to create the property procedures to be used to get and set the properties. You create a Property Set and a Property Let procedure for each property. The Property Set procedures are invoked when a Property Set statement is used in code.

objAccount.NewPurchaseAmount = 500

This statement sets the NewPurchaseAmount property in the objAccount instance of the class Account to 500. Inside the class is a Property Let procedure that assigns the value to the c_NewPurchaseAmount member variable for storage. When the Account object is queried for the value of the NewPurchaseAmount property, the Property Get procedure returns the property value by getting the value of the member variable corresponding to the NewPurchaseAmount property: c_NewPurchaseAmount.

The first Property Let procedure for the Account class object sets the value of the customer name. The VB statement that does this is as follows:

objAccount.CustName = "Joe the customer"

Here is the Property Let procedure:

Property Let CustName(ByVal sNewCustName As String)

    c_CustName = sNewCustName

End Property

The next Property Let procedure for the Account class object sets the value of CurrentBalance. However, it is not logical to allow a direct setting of the current balance. This should be calculated by adding the current balance to any new purchases. This is done in the NewPurchaseAmount Property Let procedure. Setting the CurrentBalance property produces an error:

Property Let CurrentBalance(ByVal NewCurrentBalance As Double)

    Err.Raise vbObjectError + 2, "Project1.ShowMe", "This property is read only"

End Property

This statement uses the Err.Raise command to set an error number for this invalid property setting. In the error handler, you will check for the occurrence of vbObjectError + 2.

The last Property Let statement is NewPurchaseAmount. When this is set, the new purchase amount (iPurchaseAmount) is added to the current balance of the customer (c_CurrentBalance). In the procedure, you check this balance before applying any additional transactions. If the customer is over his or her limit, do not process the transaction. Here is the NewPurchaseAmount Property Let procedure:

Property Let NewPurchaseAmount(ByVal iPurchaseAmount As Double)

    c_NewPurchaseAmount = iPurchaseAmount

    c_CurrentBalance = c_CurrentBalance + iPurchaseAmount

End Property

The first Property Get procedure for the Account class object gets the value of the customer name:

Property Get CustName() As String

    CustName = c_CustName

End Property

You use the following Property Get procedure to get the value of the customer's current balance. For now, there is only one name in the database (so that you don't get bogged down in manipulating multiple customers and lose focus on the task at hand).

Property Get CurrentBalance() As Double

    CurrentBalance = c_CurrentBalance

End Property

When the customer makes a new purchase, it is entered by setting the NewPurchaseAmount property. This property retrieves the value to the c_NewPurchaseAmount member variable and returns it to the variable in the Property Get statement, as follows:

'Property get statement

x = objAccount.NewPurchaseAmount

'Property procedure

Property Get NewPurchaseAmount() As Double

    NewPurchaseAmount = c_NewPurchaseAmount

End Property

The next step is to create the user interface. For purposes of illustration, this example uses a very simple interface. It is important to concentrate on the details of object-oriented programming and not on the implementation of databases and user interfaces.

Create a form. Add three command buttons, three labels, and five text boxes to the form (see Figure 2.5). Label the command buttons as follows:

Set Up Customer

New Purchase

Get Cust Info


Figure 2.5. The form for the Account application.

Place the following code behind the first command button (Set Up Customer). Make sure that you change the name of the command button to cmdSetUp.

Private Sub cmdSetUp_Click()

    If Text1.TEXT = "" Then

        MsgBox "The customer name must not be blank."

    Else

        clsAccount.CustName = Text1.TEXT

    End If

End Sub

This procedure adds a new customer account. For purposes of illustration, the module handles only one customer at a time. To implement additional customers, create a database file to store and retrieve information. For more information on using files to store information, see Chapter 3, "File I/O." The end of Chapter 3 explains how to store data in binary files using Visual Basic structures. The chapter also covers the use of binary chops to quickly search arrays of data for information.

The preceding procedure checks the text box to ensure that a value has been entered. If there is something in the text box, it is set as the CustName property value.

The next command button (New Purchase) posts a transaction to the account. This procedure checks the c_CurrentBalance member variable inside the Account class to ensure that the customer is not over his or her limit. In this example, the limit variable is set inside the command button's procedure. You could just as easily add a c_Limit member variable to the class to track the customer's limit. The name of this command button is cmdPostTrans; here is the procedure:

Private Sub cmdPostTrans_Click()

    'Set up our current balance and new purchase amount variables

    Dim iCurrentBalance As Double

    Dim iNewPurchaseAmount

    'This error handler is very important. If the transaction fails because the

    'customer's balance is greater than 5000, or if this transaction will take

    'them over the 5000 limit, the error is returned as a VB error.

    On Error GoTo ErrorHandler

    'Get the value from the text box

    iNewPurchaseAmount = Val(Text2.TEXT)

    'We check the value in the text box. If it is blank, we notify the user and                       'quit.

    If Text2.TEXT = "" Then

        MsgBox "The New Purchase Amount must not be blank."

        Exit Sub

    End If

    'Query the CurrentBalance property for its value (the Property Get

    'procedure for CurrentBalance is executed)

    iCurrentBalance = objAccount.CurrentBalance

    'We check the current balance to see if it is currently greater than $5000.

    'If it is, we notify the user that the transaction cannot be posted and quit.

    'See Raise in Visual Basic help for more information on structuring OLE errors.

    If iCurrentBalance > 5000 Then

        Err.Raise vbObjectError + 1, "Project1.ShowMe", _

        "Your balance is greater than $5000. This transaction is not allowed"

        Exit Sub

    End If

    'If the first check passed, we then check to see if this transaction will

    'cause the customer to go over $5000. If they will exceed $5000, they are

    'notified and we quit.

    If iCurrentBalance + iNewPurchaseAmount > 5000 Then

        Err.Raise vbObjectError + 2, "Project1.ShowMe", _

        "Your balance is currently " & iCurrentBalance & "." & _

        " This transaction causes your balance to exceed the limit. " & _

        " This transaction is not allowed."

        Exit Sub

    End If

    'The transaction cleared all of the checks, so we can post it.

    'We check the value

    If Val(Text2.TEXT) > 0 Then

        objAccount.NewPurchaseAmount = iNewPurchaseAmount

        MsgBox "The transaction has been posted. Your new balance is " & objAccount.CurrentBalance

    End If

    Exit Sub

'This error handler checks for each of the OLE errors that we defined earlier.

ErrorHandler:

    Select Case Err

        Case vbObjectError + 1

            MsgBox "Your balance is greater than $5000. This transaction is not _allowed"

        Case vbObjectError + 2

            MsgBox "Your balance is currently " & iCurrentBalance & "." & _

            " This transaction causes your balance to exceed the limit. " & _

            " This transaction is not allowed."

        Case Else

            MsgBox "Error " & Err & " " & Error$ & "ocurred."

    End Select

    Exit Sub

End Sub

The final procedure queries the Account object for the value of its properties:

Private Sub cmdAccountStatus_Click()

    Text3.TEXT = objAccount.CustName

    Text4.TEXT = objAccount.CurrentBalance

    Text5.TEXT = objAccount.NewPurchaseAmount

End Sub

This implementation is simplistic so that the methodology is not lost. With small modifications, the Account object can be set up to create multiple customers. A file containing account database information can be used to store the customer information. Additional property procedures can be defined to handle overdue bills. Other applications can query this object for customer credit ratings. The list of possibilities is endless.

The result of Account class module is an interface that exposes properties and methods to other applications for use. The inner workings of this object can become extremely complex, but interacting with the object is simple.

Now that the Account object is complete, you have to turn it into an OLE Automation object other applications and development environments can access. To do this, you create an OLE DLL. This DLL is compiled from an application that houses one or many OLE Automation objects (such as the Account object.)

The first step is to create a Sub Main() procedure so that the DLL can be compiled. Sub Main() is the startup procedure for the OLE DLL. In this case, the Sub Main() procedure doesn't require any code:

Sub Main()

End Sub

Next, select Tools | Options from the main menu and select the Project tab of the Options dialog box. From the Startup Form combo box, select Sub Main. This indicates that the project does not have a form and that the Sub Main() procedure is the entry point to the OLE DLL. In the Start Mode section, click the OLE Server button to indicate that this application will operate as an OLE server.

Then choose File | Make OLE DLL File. Enter the filename Account for the project and click OK.

The OLE DLL is automatically assigned the extension DLL unless you indicate otherwise.

Once the project is compiled, you have successfully created the Account object using OLE Automation and the class module in Visual Basic 4.0.

The final step is to use the object from another application. Start a new project and select Tools | References from the main menu. This References dialog box lists the objects other applications expose. Search this list for the Account object. Place a check next to it in the list box and click OK. Although nothing appears in the toolbar, the Account object can now be accessed by your application (Visual Basic adds a reference to the object). Recall that you compiled the Account project with the form that set and queried the different properties of the object. Add this form to your new project by selecting File | Add File and selecting the form from the original project. Run the new project. The Account form creates an instance of the exposed object and then manipulates it. Even though the class module is not included in this project, you can address it because it was included in the References dialog box. As far as your application is concerned, this object is treated the same as an object from Microsoft Excel. Unlike a chart object however, this object is not visible to the user.

Another feature of OLE objects is that private data can be stored without the fear that it will be accessed by unauthorized users. The next section discusses the concept of data hiding.

Data Hiding

Data hiding is a method of setting security for the data contained in an object. The theory behind this is similar to variable scope. For example, if you create a function inside a module and declare a variable, that variable is local and can only be seen by the function:

Function PrivateStuff

    Dim sPrivateData as String

    ...

End Function

The concept of data hiding applies in the same context to objects in Visual Basic 4.0. A variable declared at the module level is available to all applications that access the module. To ensure that other applications do not have access to a module level variable, use the Private keyword:

Private sVariable

Because the variable is private, it can be changed or eliminated without affecting other applications that access the object. This type of variable, therefore, is internal to the object and is not seen by other processes. This arrangement is most commonly used in OLE Automation. A class module is created and its properties and methods are exposed to other applications. Many of the functions inside the class module calculate items passed in by the user and return values. Variables used in these internal workings should be private and therefore of no concern to the applications accessing the class module object.

Reusable Objects and Collections

Visual Basic 4.0 has implemented a new concept called collections. A collection is an object that organizes items used in the application. Collections are conceptually similar to arrays. The items stored in the collection object are objects themselves. An example of a collection is an assortment of bitmaps. Imagine that you have an application with four forms. Each form has a toolbar that displays different icons. You can create a collections object to store all the bitmaps and add them to your toolbar when necessary.

Create a new class module by choosing Insert | Class Module from the Visual Basic menu. At the module level, enter the following declaration:

Public CInstance

On form1, add a command button and associate the following code with its Click method:

Private Sub Command1_Click()

    CreateCollection

End Sub

Insert the following code into the class module:

Sub CreateCollection()

    'New collection object

    Dim CPictures As New Collection

    Dim i As Integer

    Dim sMessageText As String

    Dim sItemName, cObject, NameList

        Dim iPictures As New Class1  ' Create a new instance of Class1.

            For i = 0 To 10

                sItemName = "Item Number " & Str$(i)

                iPictures.CInstance = sItemName ' Put name in object instance.

                If iPictures.CInstance <> "" Then

                ' Add the named object to the collection.

                CPictures.Add Item:=iPictures, KEY:=CStr(i)

            End If

        Next i

End Sub

Several types of collections are inherent parts of Visual Basic. The Forms collection contains all the currently loaded forms. The Controls collection contains all the controls on a form. The Printers collection contains all the available printer objects. Additionally, you can create a custom collection of objects. This type of collection is used to keep track of a group of items in your application. For example, you may want to hold a group of MDI forms in one collection. The advantage of creating a collection of these forms is that all the forms can be acted on at the same time using the For Each statement. The following example adds five forms to a collection:

'Module Level

Public cFormCollection as New Collection

cFormCollection.Add fForm1

cFormCollection.Add fForm2

cFormCollection.Add fForm3

cFormCollection.Add fForm4

cFormCollection.Add fForm5

To act on all of the forms in the collection, use the For Each statement:

For Each Form in cFormCollection

     Debug.Print Form.Name

Next Form

You can address an item in a collection in one of several ways. The cFormCollection example used earlier in this chapter can address fForm1 in any of the following ways:

cFormCollection("fForm1")

addresses fForm1.

cFormCollection (1)

In all these cases, the object is accessed by its index in the collections object. Actions can be taken on each form in the collection. For example, if you want to set the left and top of all of the forms at the same time, do the following:

For Each Form in cFormCollection

     Form.Top = 100

     Form.Left = 100

Next Form

Manipulating Controls

Visual Basic 4.0 now includes the With...End With and the For Each keywords.

The With...End With statement allows multiple actions to be taken on the same control without repeating the control name. The following example changes several properties on Form1 using the With...End With statement:

With Form1

     .Caption = "Form 1"

     .BackColor = H00C0C0C0&

     .Height = 8000

End With

The For Each statement is used to manipulate a group of controls within a loop. Imagine that you have a form with ten command buttons, two text boxes, and one label. You want to align all these controls along the left side of the form. Traditionally, the following code is used:

For X = 1 to 10

     Command1(X).Left = 200

Next X

For X = 1 to 2

     Text1(0).Left = 200

Next X

Label1.Left = 200

This code also assumes that the command buttons are contained in a control array. The manipulation of multiple controls becomes more of an issue as the number of controls on a form increases. Visual Basic 4.0 includes the For Each statement that allows manipulation of a group of controls on a form, in a collection, and so on. The same action performed by the preceding code can be accomplished using the following For Each statement:

For Each Control in Form1.Controls()

     Control.Left= 200

Next Control

All the controls on the form are set at the same time using only one statement.

Upgrading Existing Projects to Visual Basic 4.0

Projects created in earlier versions of Visual Basic can easily be upgraded to Visual Basic 4.0. During the upgrade, Visual Basic changes the format of project files so that they can be opened in version 4.0. Visual Basic 1 used a binary format; Visual Basic 2.0 and 3.0 use both text (FRM) and binary (FRX) formats for their files. This changes in Visual Basic 4.0: all project files in VB4 are in text format only. Binary project files are no longer a part of Visual Basic.

The next section explains how to upgrade to version 4.0 projects created in previous versions of Visual Basic. The quick steps are provided first and are followed by a detailed explanation of project conversion.


CAUTION

It is highly recommended that you read the detailed explanation for project conversion before using the quick steps. Project files converted to Visual Basic 4.0 cannot easily be converted back! There are several pitfalls to watch out for along the way!

Quick Steps for Upgrading a Project to Visual Basic 4.0

Follow these simple steps to convert to Visual Basic 4.0 to format a project created in an earlier version of Visual Basic:

  1. Make a backup copy of your existing project (refer to the following section for important details about copying a project).

  2. Update the copied project's MAK file.

  3. Open the copied project in Visual Basic 4.0.

  4. Choose Yes from the Custom Control Upgrade dialog box.

  5. Answer OK for All in the Microsoft Visual Basic dialog box that asks whether it should upgrade project files to the new version of Visual Basic.

  6. If your project uses Data Access Objects (DAOs) such as databases, Dynasets, and so on, choose Add in the next Visual Basic dialog box that appears. (This dialog box begins with the text This project was developed in a previous version of Visual Basic.)

  7. If you have declared any arrays using the ReDim statement and these arrays were not first declared using either Dim or Static, VB4 produces an error. Enter the initial declarations for these variables.

It's that simple. Your project is now converted to Visual Basic 4.0 format.

If you did not use Option Explicit in your Visual Basic version 3.0 modules, Visual Basic 4.0 produces an error for any variables that are not declared. Select Tools | Options from the main menu and deselect the Require Variable Declaration checkbox. This should allow your project to run. Once the project runs successfully, add the variable declarations to your project and then reselect the Require Variable Declaration checkbox.


NOTE

You should always use Option Explicit when programming in Visual Basic. This statement prevents many errors caused by misspelling or misusing variable names and can save a great deal of time during debugging. Once your project is running smoothly, add a declaration for each variable. Then select Tools | Options from the main menu and select the Require Variable Declaration checkbox.

Project Conversion Explained

This section described several things you should consider when converting a project from a previous version of Visual Basic to Visual Basic 4.0.

More than likely, you will want to save a copy of the project in the current version's format. You must be very careful to properly copy the existing project before the conversion is undertaken. (Once a project is converted, it is not easily converted back.)

Imagine that you are converting a project from Visual Basic 3.0 to Visual Basic 4.0. The project has five forms and two modules. It also includes CONSTANT.TXT and several VBXes. Following is an example of the version 3.0 project's MAK file:

DATABASE.FRM

C:\VB\ABOUT.FRM

C:\VB\TOP10.FRM

TOOLBAR.FRM

C:\PROJECTS\OPEN.FRM

C:\PROJECTS\MODULE1.BAS

MODULE2.BAS

C:\VB\CONSTANT.TXT

C:\WINDOWS\SYSTEM\THREED.VBX

MHTR200.VBX

MHCOMD.VBX

ProjWinSize=75,765,254,422

ProjWinShow=2

IconForm="Project"

Title="PROJECT"

ExeName="PROJECT.EXE"

Let's start by saying that this is a poor way to construct a project. Note that the first entry, DATABASE.FRM, is not preceded by a path, indicating that the form file is located in the same directory as the project's MAK file. However, the second form file, C:\VB\ABOUT.FRM, is located in the C:\VB directory. In other words, the files of the project are split among several directories. Imagine that this project's MAK file is stored in the directory C:\PROJECTS\PROJECT1.


CAUTION

Do not perform the steps in the next paragraph. They are an example of how to corrupt an existing project!

To convert the project to Visual Basic 4.0, suppose that you copy all files in the directory C:\PROJECTS\PROJECT1 to the directory C:\PROJECTS\VB4PROJ (your VB4 project directory). Next, you open the project stored in C:\PROJECTS\VB4PROJ in Visual Basic 4.0. VB4 states that the project files were saved in a previous version of Visual Basic and will be converted to Visual Basic 4.0 format when saved. You answer OK to All to convert all the files in the project and then save the project.

You have just made a serious error. All the project files that were not stored in the C:\PROJECTS\PROJECT1 directory were not copied to the directory C:\PROJECTS\ VB4PROJ. These files are still referenced by the MAK file in C:\PROJECTS\VB4PROJ however, and are therefore converted to VB4 format. The problem is that there is no longer a version 3.0 copy of these files; the originals have been converted to VB4's format.

The solution to this dilemma is to properly prepare the project before copying and converting it. Here are the steps:

  1. Create a new directory to store the VB4 version of the project.

  2. Copy all the project files in the current project directory to the new project directory.

  3. Open the project's MAK file in the new directory. Look for any project files that reference a path (for example C:\VB\TOP10.FRM).

  4. Copy the files that reference a path to the new project directory. In this example, copy the file C:\VB\TOP10.FRM to C:\PROJECTS\VB4PROJ. Do not copy VBX, OCX, or DLL files in the WINDOWS or WINDOWS\SYSTEM directory.

  5. Remove the path statement from the project-file entries in the MAK file (for example, C:\VB\TOP10.FRM becomes TOP10.FRM). Do not remove the path from the VBX, OCX, or DLL files in the WINDOWS or WINDOWS\SYSTEM directory.

  6. Remove any reference to CONSTANT.TXT. This file has been incorporated into Visual Basic 4.0 and does not need to be added. Be sure to move any items you may have added to CONSTANT.TXT to a module.

  7. Save and close the project MAK file.

  8. Run Visual Basic and convert the project to the Visual Basic 4.0 format.

Following is an example of the project MAK file after modification:

DATABASE.FRM

ABOUT.FRM

TOP10.FRM

TOOLBAR.FRM

OPEN.FRM

MODULE1.BAS

MODULE2.BAS

C:\WINDOWS\SYSTEM\THREED.VBX

MHTR200.VBX

MHCOMD.VBX

ProjWinSize=75,765,254,422

ProjWinShow=2

IconForm="Project"

Title="PROJECT"

ExeName="PROJECT.EXE"

If you store all your VBX, OCX, or DLL files in a common directory and all Visual Basic projects access this directory, you do not have to copy those files to the new project directory. In this case, leave the path statement on the entry in the MAK file so that it can be referenced by Visual Basic.


TIP

Visual Basic loads project files in a specific order. To speed up the loading of a project, change the order in which project files are listed in your MAK file. Place all VBX files in the MAK file first, followed by form (FRM) files, and finally by module (BAS) files. Sort the files alphabetically within each group. Projects (especially large ones) can load up to 100 percent faster with this arrangement.

In the cleaned-up project MAK file, notice that I did not remove the path from the line C:\WINDOWS\SYSTEM\THREED.VBX. The indicated directory is the natural location for this VBX because it is a part of Windows. In addition, there is no need to copy this file to the new project directory.

Upgrading Custom Controls

Visual Basic 4.0 can automatically upgrade the custom controls in a project. To choose to have Visual Basic 4.0 upgrade controls, select Tools | Options from the main menu. This displays the Options dialog box. Click the Advanced tab and select the Update Custom Controls checkbox. When this option is selected, Visual Basic searches for an updated version of the control to add to the project. This control must be an OCX file (OCXs are the new generation of custom controls for Visual Basic).

Many existing custom controls have been updated for Visual Basic 4.0 and several new controls have been added. Additionally, many of these controls provide Windows 3.1 applications with a Windows 95 look. The following sections describe custom controls you can use to improve functionality and graphical presentation. Controls available in Visual Basic 3.0 are provided because of their importance and in case you were not aware that they existed.

Communications Control

The Communications control provides a way for your applications to communicate through the serial port of the computer. A common use for the control is in the development of applications that communicate over telephone lines. If your application outputs files that are transferred from one PC to another, or calls and connects to another application through a modem, this control is a lifesaver. The Communications control simplifies the process of serial communications with an array of functions and provides an alternative to the tedious, manual operations normally required in serial communications.

The following code ensures that the modem is operational, receives data coming in over the modem, and then places the data in a file:

Sub Receive_Data ()

    'Select communications port 1

    Comm1.CommPort = 1

    ' Open the port.

    Comm1.PortOpen = True

    ' Set the modem to 14000 baud, Even parity, 8 data bits, 1 stop bit

    Comm1.Settings = "9600,E,8,1"

    'Set HandShaking off (default). Handshaking is a safety check to ensure that               'data is not

    'transmitted to the input buffer faster than it can be handled, resulting in        'the loss of data.

    Comm1.HandShaking = 0

    'We are receiving the data in 32K blocks. If I set this to 0, the entire buffer             'is read at once.

    Comm1.InputLen = 32000

    'If there is data, receive it and place it in a file

    'Open the file

    x = FreeFile

    sFileName = "C:\PROJECT\PROJECT1\MODEM.TXT" for input as x

    'Continue placing 32000 byte chunks into sData until the modem buffer is empty.

    Do While Comm1.InBufferCount > 0

        'Input the data in sData.

        sData = Comm1.Input

        'Write the data that was received in sData and place it to the file

        Print #x, , sData

    Loop

    'Close the file

    Close x

    ' Close the serial port.

    Comm1.PortOpen = False

End Sub

Gauge Control

The Gauge control is a graphical tool for displaying the completion percentage of operations. There are four different styles of display, which are set using the Style property:

Style


Description


Horizontal Fill

The inner area is filled from left to right. This is much like a standard percentage completion bar.

Vertical Fill

The inner area is filled from bottom to top.

Semi-Needle

The needle is drawn in a semicircular arc from left to right.

Full-Needle

The needle is drawn in a full 360-degree circle from left to right.


NOTE

The size and shape of the inner area of the Gauge control cannot be modified by the programmer. The only control is through the Style property.

The following example sets up a gauge to fill with values from 0 to 100. Each of the gauge styles is demonstrated:

Sub UpdateStatus()

    'Set the height (Set the form's scale mode to PIXEL)

    Form1.ScaleMode = 3

    Gauge1.Height = 30

    'These 4 properties set how far from the control's edge the bar paints

    '(0 is at the edge).

    Gauge1.InnerTop = 5

    Gauge1.InnerLeft = 5

    Gauge1.InnerBottom = 5

    Gauge1.InnerRight = 5

    'Set the minimum and maximum values (if min = 100, then the status

    'bar is full at 100

    Gauge1.MIN = 0

    Gauge1.MAX = 100

    Gauge1.NeedleWidth = 10

    'Set the ForeColor to red

    Gauge1.ForeColor = QBColor(4)

    For i = 0 To 3

        'Set the gauge to each of the fill styles

        Gauge1.Style = i

        'Fill the gauge from 0 to 100

        For x = 1 To 100

            Gauge1.VALUE = x

            'DoEvents stops and paints the control. Without this the control would             'appear

            'at 0 throughout the operation, and then suddenly appear at 100.

            DoEvents

            'slow it down some

            For y = 1 To 10000

            Next y

        Next x

    Next i End Sub

Graph Control

The Graph control allows you to add charts and graphs directly to your project's forms. This control has been updated in Visual Basic 4.0. Using the GraphStyle property, you can set the chart to any of the following types:

Type


Description


2-D or 3-D Pie

This chart is used for displaying percentage-related data. Each slice of the pie represents a data element.

2-D or 3-D Bar

This chart is used for displaying counts for items in a category (for example, the number of hits for each player on a baseball team). Each bar represents a data element. The items do not necessarily add up to 100 percent.

Gantt

This chart is commonly used in project management to view deadlines and dependencies. When applied in this manner, each element of the chart represents the task for a specific person on the team. Tasks and deadlines can be easily viewed. The chart also demonstrates the impact when a deadline is missed.

Line

This chart is used for plotting points. For example, each point represents the number of orders outstanding on a given day. The points are connected by a line that demonstrates trends.

Area

This chart is used to show data over time. Picture this as similar to a bar chart whose bars are connected. Instead of the chart's area being one color, however, the area is separated horizontally into categories. In other words, this data is stacked, and the top of the area represents the sum of all the categories. Imagine that an area chart represents sales in five categories over 12 months. The y (horizontal) axis represents the months (much like a bar chart) and the x (vertical) axis represents the number of items sold. In January, 10 items were sold in each of the categories. The total value for January is 40 (four separate colors stacked on top of each other, each representing a category). This continues throughout the year to complete the chart. Each month's data is connected (not broken like a bar chart).

ScatterGram

This type of chart is most commonly used for plotting engineering data. Another use is to demonstrate the results of a survey given to an assortment of age groups. For example, one of the axes may represent responses to questions on a survey and the other axis breaks the respondents out into different ethnic groups. Each response is represented by a dot (point) on the chart.

HLC

The most common use for this chart is in the charting of stock (High, Low, Close)market data. The chart shows the highest and lowest values for a given time period as well as the value at closing (end of the time period).

Key Status Control

When the Key Status control control is clicked, it changes the state of one of the following keys:

Caps Lock

Num Lock

Insert

Scroll Lock

This control appears as a key that can be clicked with the mouse. The Style property is used to set the type of key pressed by the Key Status control. The Value property is used to set the control's state (TRUE = On, FALSE = Off). The user can click the control with the mouse to change the state (Value) of the selected key or use the corresponding key on the keyboard.

Spin Button Control

If your application currently uses a text box or a masked edit box in which the user enters a number (for example, the number of seconds to wait before timing out an operation), the Spin Button control can come in handy. The spin button works in combination with another control (such as a text box) to allow the user to select a value. The control has an up and a down arrow. When the user click one of the arrows, the value is changed in that direction. Using the SpinUp and SpinDown events, you can control the amount by which the control is increased or decreased. The following example increases the value in the text box by 5 each time the up arrow is clicked:

Sub Spin1_SpinUp

    Dim iValue as Integer

    Dim iIncrementer as Integer

    iIncrementer = 5

    'Get the value out of the text box and store it in a variable

    iValue = Val(Text1.Text)

    'Increment the variable

    iValue = iValue + iIncrementer

    'Put the value back into the text box

    Text1.Text = Str$(iValue)

End Sub

The value placed in the text box can then be used to set the value for another control's property or to pass into a function.

SSTab Dialog Control

The SSTab Dialog control is a tab control similar to the one used in the Options section of Microsoft Word or Excel. Each tab can contain other controls. When a tab is selected, only its controls are visible; the controls on the other tabs are hidden. You have control over the number of tabs, the number of rows, and the style and size of each tab. It is also possible to display a graphic on a tab.

Status Bar Control COMCL32.OCX (32-Bit Only)

This control is available only in Microsoft Windows 95 and Windows NT 3.51 and higher (32-bit) operating systems. The Status Bar control is placed at the bottom of a form to display information about an application. For example, in Microsoft Word, the status bar displays the current page, time, and so on. This control can be divided into as many as 16 different panel objects (sections). Each panel object is a member of a Panels collection. You can set up functions that determine what data (or picture) is displayed in each of the sections. Seven standard Style property values allow you to display data such as date and time automatically—without writing additional code. The following example adds eight panels to the status bar and sets each to a system function:

Sub CreateStatusBar()

    Dim iRet As Integer

    'Add 8 segments to the status bar.

    For iRet = 1 to 8

        StatusBar1.Panels.Add

    Next iRet

    'The WITH operator allows us to address the status bar panels. 

    'Here we set each panel to one of the  system functions:

    With StatusBar1.Panels

        .Item(1).Style = sbrText    ' Text or picture

        .Item(2).Style = sbrCaps    ' CAPS Lock Key

        .Item(3).Style = sbrNum     ' Number Lock Key

        .Item(4).Style = sbrIns     ' Insert Key

        .Item(5).Style = sbrScrl     'Control Key (Ctrl)

        .Item(7).Style = sbrTime     'Current Time

        .Item(8).Style = sbrDate     'Current Date

    End With

End Sub

Slider Control COMCL32.OCX (32-Bit Only)

The Slider control is used to set a value in a simplified manner. It is an alternative to having the user enter a value in a text box, validating the value, and then applying the value to your function. The Slider control contains a bar that can be moved across a scale with tick marks to set a value. You have control over the start and end values as well as the amount the value is incremented each time the bar is moved to a different tick mark. The bar can be moved by clicking and dragging it with the mouse, clicking on either side of it, or by using the arrow keys on the keyboard.

ImageList Control COMCL32.OCX (32-Bit Only)

The ImageList control is designed to store images for use by other controls. For example, this control can store all the bitmaps used on all the application's toolbars. A bitmap is assigned to the button by assigning it to the picture property of the object. The following code assigns a series of bitmaps to an ImageList control. It then assigns the appropriate bitmap to the and image control at runtime:

'Assign the bitmaps to the ImageList object

For X = 0 to 10

    ImageList1.ListImages(x) = "C:\PROJECT\BITMAPS\BITMAP" & X " ".BMP"

Next X

'Find out which bitmap the user wants to see.

iRet = InputBox("Enter a bitmap number", "Show Bitmap", 0)

'Show the bitmap in the picture box.

Set Form1.Image1.Picture =  ImageList1.ListImages(iRet)

You can store bitmaps, icons, or a combination of both. The only restriction is that the images must be the same size—and you are limited there only by system memory.

ListView Control COMCL32.OCX (32-Bit Only)

The ListView control allows you to display the items stored in an ImageList control. This control has four different views that can be set using the View property:

Large Icons

Small Icons

List

Report

The ImageList control is used to supply the icons as well as the text description for the displayed item. Keep in mind that the ListView control uses an ImageList control as the source of its data. ListView is designed to be used in conjunction with the ImageList control.

TreeView Control COMCL32.OCX (32-Bit Only)

The TreeView control is used to display a hierarchy of information. This control resembles the functionality of the Windows 3.1 File Manager. Items can be added or removed from the list at runtime and the list can be rearranged. Items contain + and — signs to indicate whether or not the node is expanded or collapsed. Nodes can be expanded and collapsed with the mouse or by using the left-arrow and right-arrow keys. You can traverse the tree using the following properties:

Property


Description


Root

Returns a reference to the root node object of a selected node.

Parent

Returns or sets the parent object of a node object.

Child

Returns a reference to the first child of a node object.

FirstSibling

Returns a reference to the first sibling of a node object.

Next

Returns a reference to the next sibling of a node object.

Previous

Returns a reference to the previous sibling of a node object.

Bitmaps can be displayed in front of each item. The bitmaps are supplied by the ListItem control. Several different styles can alter the appearance of the control:

Style


Description


0

Text only

1

Image and text

2

Plus/minus and text

3

Plus/minus, image, and text

4

Lines and text

5

Lines, image, and text

6

Lines, plus/minus, and text

7

(Default) Lines, plus/minus, image, and text

Toolbar Control COMCL32.OCX (32-Bit Only)

The Toolbar control allows you to create a toolbar for your application. This control uses a series of buttons contained in a Buttons collection. Each of the buttons executes an application function. Both pictures (Image property) and text (Caption property) can be placed on each button. Images are supplied through the ImageList control. At runtime, you can add a button to the toolbar or remove one using the Add or Remove method. The Button_Click() event is used to respond to a user pressing one of the toolbar buttons.

Double-clicking the toolbar at runtime brings up the Customize Toolbar dialog box. This dialog box allows you to manipulate the items on the toolbar. Items can be displayed, hidden, or rearranged. If you set the AllowCustomize property to TRUE, users can rearrange the toolbar buttons by holding down the Shift key and dragging the buttons.

RichText Box Control RICHTX32.OCX (32-Bit Only)

The RichText Box control is a text-editing control that is a significantly enhanced version of the text box. This control supports RTF formats (such as the one used in Microsoft Word). This control allows you to load a file directly into it, edit the contents of the file, and then save the file to disk. This is accomplished using the LoadFile and SaveFile methods. If you want to save only the portion of the text the user has selected, use the SelRTF property. The RichText Box control is a data-aware control you can bind to any memo field in a Microsoft Access database. The contents of the control can also be printed using the SelPrint method. You can also make the selected text bold and italic and set the color of the text. (Note that only the selected text can be modified.)

Another advantage this control has over the text box is that it is not limited to 64K of data. The following example loads a file into the RichText Box control. Once the user has selected some of the text, the format is changed and only the selected text is saved back to the file. Imagine that the filename C:\WORD\REPORT.DOC is passed to the function:

'Load the file into the control

Function OpenRTFFile(sFileName as String)

    RichTextBox1.LoadFile(sFileName, rtfRTF)

    MsgBox "Please select the text to be updated and click Update", 0, "Select File"

End Function

Next, the user highlights some text and clicks Update:

'Updates the file. This function returns only the selected text to the file.

'All other data is erased.

Sub UpdateRTFFile()

    Open "mytext.rtf" For Output As iFileNum

    Print #1, RichTextBox1.SelRTF

    Close iFileNum

End Sub

ProgressBar Control COMCL32.OCX (32-Bit Only)

The ProgressBar is a 32-bit control used to display the status of an operation. Each update segment is a small square block in the color of your choice. This control is similar to the status bar Microsoft Word uses when saving a document. The following example displays a progress bar while an array is being written to a file:

Sub ProgressBar()

    Dim iMin as Integer

    Dim iMax as Integer

    Dim sDataArray() as String

    Dim iIncrement as Integer

    Dim I as Integer

   'Show the progress bar

    Progress1.Visible = True

   'Fill the array with data

    ...

    'Calculate the increment

    iIncrement = UBound(sDataArray) + 1/100

    'Set up the minimum and maximum progress bar values

    ProgressBar1.Min = 0

    ProgressBar1.Max = 100

    'Open a file to write the sDataArray() to.

    x = FreeFile

    sFile = "C;\PROJECTS\PROJECT1\REPORT.TXT"

    Open sFile for output as x

    'Write the array to the file and update the progress bar

    For I = 0 to UBound (sDataArray)

        Print #x, , sDataArray(i)

        ProgressBar = iIncrement + 1

    Next I

    'Close the file

    Close x

    'Hide the progress bar

    Progress1.Visible = False

End Sub

The preceding sections covered some of the OCXs provided with Visual Basic 4.0.


NOTE

Visual Basic 4.0 includes a feature that allows you to lock down the controls on a form. Once you have converted your project to Visual Basic 4.0, open each of the project's forms and click the Lock Controls toolbar icon. This action prevents controls on the form from being resized or moved accidentally. Selecting this option locks all controls on the form. More than likely, changes you make to a project after conversion are primarily code changes. The control-lock option prevents form objects from moving and ensures that the Visual Basic 4.0 user interface matches the one developed in Visual Basic 3.0.

32-Bit Support and Conditional Compilation

Visual Basic 4.0 is available in both 16-bit and 32-bit versions. To create applications that can be used in both environments, conditional compilation has been added to the Visual Basic language. Conditional compilation allows you to compile certain code only under certain conditions. For example, if the executable file being created is going to be run on a 16-bit system, API functions from the 16-bit libraries must be added. To easily change the executable file for use in a 32-bit system (which requires different function declarations), use conditional compilation. When upgrading a project to Visual Basic 4.0, consider the changes required to make the application compatible with the 32-bit version of Visual Basic. Note that 32-bit applications run only on Windows 95 and Window NT operating systems.

Conditional compilation has two components: the constant definition and the compiler directive. Visual Basic provides the following constants:

You can create your own compiler constants by declaring them in the following manner:

#Const MyConstant = True

To use this constant, use the #If...#Then...#Else directive:

#If MyConstant = True Then

    For x% = 1 to 1000

        Print "Hello"

    Next x%

#Else

    For x% = 1 to 1000

        Print "Goodbye"

    Next x%

#End If

Compile the project; if the constant MyConstant equals TRUE, the first part of the #If statement is added to the executable. Otherwise, the portion after #Else is added. Under conditional compilation, any code not selected is not added to the executable file. This arrangement allows you to upgrade existing applications to 32-bit Windows platforms without writing separate versions of the project (or writing one version with a significantly larger executable file).

Another implementation of conditional compilation is for the purposes of debugging. Imagine that you want to execute a function that writes data to a file for debugging purposes. Also imagine that these data-writing functions are scattered throughout your project. Once the project is complete and ready for a final executable, it is difficult to traipse through the project and find all the debug-only code. If you use conditional compilation, however, you can easily remove these debug functions:

'General Declarations

#Const DebugVersion = True

Private Sub Command1_Click()

    Dim x As Integer

    Dim iRet As Integer

    Dim sFileName As String

    'Run a normal application function

    x = NormalApplicationFunction

    'If the DebugVersion constant is set to true then include the debug code in the        'executable

    #If DebugVersion = True Then

        iRet = GetDebugStats

    #Else

        'In this case, we really don't need an #Else statement

    #End If

End Sub

Function NormalApplicationFunction

    #If DebugVersion = True Then

        Dim x as Integer

        Dim Temp as String

        Dim DebugArray()

        For x = 1 to 50

            'Place some code here that places data into the Temp variable

            ReDim Preserve DebugArray(x)

            DebugArray(x) = Temp

        Next x

    #End If

    'Normal function body

End Function

Function GetDebugStats

    #If DebugVersion = True Then

        Dim iRet as Integer

        Dim iFileNum as Integer

        Dim sFileName as String

        iFileNum = FreeFile

        Open sFileName for Output as iFileNum

        For iRet = 0 to UBound (DebugArray) 'DebugArray was previously created and 'filled with data

            Print #x, DebugArray(iRet)

    #End If

End Function

Here are some considerations. First, if the DebugVersion constant is set to FALSE, the code iRet = GetDebugStats in Sub Command1_Click() is not included in the executable file. Additionally, none of the code in the function GetDebugStats is included. Although you can achieve this same functionality with standard variables, the portion of the code that executes the debug function and the debug function itself are added to the executable file, increasing its size. Second, the #Const declaration is local in scope; global #Const declarations are not allowed. The solution to this limit is to use the Advanced Options tab in the Options dialog box to declare the constant. Select Tools | Options from the Visual Basic menu and select the Advanced tab. Enter the global constant declaration in the Conditional Compilation Arguments field at the bottom of the dialog box.

Another use for conditional compilation is portability from 16-bit to 32-bit systems. Imagine that you are declaring the function OSGetPrivateProfileString. On a 16-bit system, this function is in the library KERNEL. On 32-bit systems, it is in the library Kernel32. The function used on the 32-bit system does not work on a 16-bit system. Although the 16-bit function works on a 32-bit system, it does not perform as well as the 32-bit function and is therefore not a good choice. To declare the proper function at the proper time without having to rewrite code, use the following conditional compilation statement:

#If Win16 Then  'Win16 (16-bit) declaration

    Declare Function OSGetPrivateProfileString% Lib "KERNEL" Alias "GetPrivateProfileString" _

(ByVal AppName$,_ 

    ByVal KeyName$,_ 

    ByVal keydefault$,_ 

    ByVal ReturnString$,_ 

    ByVal  NumBytes As Integer, ByVal FileName$)

#Else  'Win32 declaration

    Declare Function OSGetPrivateProfileString% Lib "Kernel32" Alias "GetPrivateProfileStringA"_     

(ByVal AppName$,_ 

ByVal KeyName$,_ 

ByVal keydefault$,_ 

ByVal ReturnString$,_ 

ByVal NumBytes As Integer, ByVal FileName$)

#End If

It is important to understand what is actually happening here. When the source code is compiled in the 16-bit operating environment, the 16-bit portion of the code is added to the executable; the 32-bit code is omitted. When compiled in the 32-bit operating environment, the opposite occurs. The size of the executable is not increased because the project does not have to be compiled for both 16-bit and 32-bit operating systems.

Make EXE Options

Another way to take advantage of the new features of Visual Basic 4.0 is simply to recompile existing projects in Visual Basic 4.0. Visual Basic now provides an EXE Options dialog box you can use to enter information about the project directly into the executable file. This option also places a version number in the executable file for future reference. Additionally, auto-incrementing of version numbers is available. To set executable file options for a project, select File | Make EXE File. The Make EXE File dialog appears. Choose the Options button to display the EXE Options dialog box.

Enter the appropriate version information in the dialog box and choose OK. This information is then added to the executable file by Visual Basic.

Setup Wizard

Once you have upgraded your project to Visual Basic 4.0 and have created a new executable file, you can take advantage of one more new feature. Visual Basic 4.0 offers a Setup Wizard that creates installation disks for your project. This wizard allows you to choose the files to include in the project, compresses these files, and places them on floppy disks for distribution. A SETUP.EXE file is provided on the setup disk to install the application on the end user's PC. (SETUP.EXE is generated automatically by the Setup Wizard.)

To use the Setup Wizard, double-click the Application Setup Wizard (16-bit or 32-bit) icon in the Microsoft Visual Basic 4.0 program group (Program Manager), or run the program C:\VB4\setupkit\kitfiles\setupwiz.exe. Then follow these Setup Wizard steps (each of the following steps represents a new Setup Wizard dialog box):

  1. Type the name of the Visual Basic project for which you want to build a setup program. Choose the ... button to open a common dialog box to choose the path. Click the Rebuild the Project's EXE File checkbox to rebuild the project. Choose the Next button.

  2. If your project uses the Data control or Data Access Objects (such as Dynaset), the Setup Wizard displays the Step 2 dialog box. Choose the database drivers associated with your application. You may select more than one driver. These drivers are included in the distribution disks.

  3. Select the location where the setup files are to be placed. Click either the Disk Drive or Directory option button and then select the location on that drive where you want the files to be placed.

  4. If Visual Basic detects the use of OLE servers in the project, they are added to the list box in this dialog box. If an OLE server is necessary for the project but is not listed, choose Add OLE Servers to add a server to the distribution disks.

  5. The wizard may display a dialog box that allows you to remove dependency files. Use this dialog box to remove any files you are not legally allowed to distribute as well as any duplicate files (files users already have on their PCs).

  6. Determine the type of application being installed. The Step 6 dialog box has the following options:

    Install In Application Directory. This option indicates that this is a stand-alone application to be installed in its own directory.

    Install as OLE Automation Shared Component. This option indicates that this application is an OLE Automation component. If this option is selected, the application is installed in the shared components directory, \OLESVR. The 32-bit versions of Visual Basic 4.0 also have an OLE Automation Provider checkbox; when this checkbox is selected, the files AUTMGR32.EXE and AUTPRX32.DLL are added to the setup program.

  7. The final step displays a list of the files to be distributed with the application and allows you to add, remove, and view the details about files. If you are unsure about the reason a certain file is included, the Dependency Of combo box displays the dependency or the reason that the file has been included. Choose Finish to place the application files on the chosen media (for example, a floppy disk). If floppy disks are the media of choice, you are prompted to insert additional disks as needed.

Once you complete step 7, your setup disks are complete and ready for distribution.

Summary

This chapter outlined many of the new features provided in Visual Basic 4.0. In particular, the following items were covered:

Previous Page TOC Next Page